#ifndef NODELINKRENDERING_H
#define NODELINKRENDERING_H

#include <QObject>
#include <vtkRenderer.h>
#include <vtkPolyData.h>
#include <anatomicaltemplate.h>
#include <correlationmatrix.h>
#include <anatomicallink.h>
#include <anatomicalregion.h>
#include <vtkMapperCollection.h>
#include <vtkActorCollection.h>
#include <linkfilter.h>
#include <QVector>
#include <QStack>

bool deviationLessThan(AnatomicalLink *link1, AnatomicalLink *link2);

class FunctionalNetwork : public QObject
{
    Q_OBJECT

signals:
    void taskUpdate(int current, int max);
	void viewUpdateRequired();
	void matrixChanged();
	void selectionChanged();

public:
	enum RegionRenderMode
	{
		LinkRenderer,
		RegionRenderer
	};

    FunctionalNetwork();
    FunctionalNetwork(AnatomicalTemplate *templat);
    ~FunctionalNetwork();

    void attachToRenderer(vtkRenderer *rend);
    void detachFromRenderer(vtkRenderer *rend);
    void setTemplate(AnatomicalTemplate *templat);
    void setCurrentAverageMatrix(CorrelationMatrix *matrix);
	void setCurrentIndividualMatrix(CorrelationMatrix *matrix);

	QVector<AnatomicalLink*>& getLinksSortedByDeviation();
    CorrelationMatrix *getCurrentIndividualMatrix();
	CorrelationMatrix *getCurrentAverageMatrix();
    AnatomicalTemplate *getTemplate();
    AnatomicalLink* getLink(int i, int j) const;
	AnatomicalLink* getLink(AnatomicalRegion* regA, AnatomicalRegion *regB) const;

	AnatomicalLink* getLinkByRegionIds(int id1, int id2) const;
	AnatomicalRegion* getRegionById(int id) const;

    //void setSelection(const QVector<AnatomicalRegion*>& select);
    void setSelection(const QVector<AnatomicalLink*>& select);
	void setSelection(const QVector<AnatomicalRegion*>& select);
	
	inline void setSelectedRegion(AnatomicalRegion* region) { selRegion = region; }
	inline AnatomicalRegion *selectedRegion() { return selectedRegionUndoStack.top(); }

	QVector<AnatomicalLink*>& getSelection() const;
	inline void setRenderMode(RegionRenderMode m) { pmode = m; }
	inline RegionRenderMode renderMode() { return renderModeUndoStack.top(); }
	void undoSelection();
	void redoSelection();

	void addFilter(LinkFilter* filt);

	inline bool redoPossible() { return selectionRedoStack.size() > 0; }
	inline bool undoPossible() { return selectionStack.size() > 0; }

	double minimumDistance() const;
	double maximumDistance() const;
	inline double std() const { return stdVal; }
	inline double mean() const { return meanVal; }

	void updateView();
	void update();

	QVector<AnatomicalLink*>& getLinks() const;
	QVector<AnatomicalRegion*>& getRegions() const;

    void init();

private slots:
	void on_filterChanged(LinkFilter*);

private:
    static int getCollectionIndex(int row, int col);

	void recreateOrderedList();

	void recalcMean();
	void recalcStd();

	double meanVal;
	double stdVal;
    AnatomicalTemplate *aTemplate;
    CorrelationMatrix *avgMatrix;
	CorrelationMatrix *indivMatrix;

	RegionRenderMode pmode;

	QStack<QVector <AnatomicalLink*> > selectionStack;
	QStack<QVector <AnatomicalLink*> > selectionRedoStack;

	QStack<RegionRenderMode> renderModeUndoStack;
	QStack<RegionRenderMode> renderModeRedoStack;

	QStack<AnatomicalRegion*> selectedRegionUndoStack;
	QStack<AnatomicalRegion*> selectedRegionRedoStack;

	AnatomicalRegion* selRegion;

	QVector<LinkFilter*> Filters;

	QVector<AnatomicalLink*> *links;
    QVector<AnatomicalLink*> LinkList;
};

#endif // NODELINKRENDERING_H
